Powershell scripts/Agentless Scanning CMK support/AddCmkPermissions.ps1 (159 lines of code) (raw):
<#
.SYNOPSIS
This script iterates over all VMs in specified subscriptions, identifying those with Customer Managed Keys (CMK).
It provides 2 options for applying permissions:
Option 1 - Key Vault level (note: you'll need to re-run the script when new Key Vaults are created).
Option 2 - Subscription level.
.PARAMETER Subscriptions
An array of Azure Subscription IDs.
.PARAMETER DryRun
A switch parameter to simulate the process without making changes.
.EXAMPLE
.\AddCmkPermissions.ps1 -Subscriptions "Subscription1", "Subscription2" -DryRun
.\AddCmkPermissions.ps1 -Subscriptions "Subscription1"
#>
param (
[Parameter(Mandatory=$true)]
[string[]]$Subscriptions,
[switch]$DryRun
)
if (-not $PSBoundParameters.ContainsKey('DryRun')) {
$DryRun = $false
}
# Prompt for permission application level
$option = Read-Host "Select permission application level:
(1) Key Vault level (Note: you'll have to run the script again when new Key Vaults are created)
(2) Subscription level
"
if ($option -eq "1") {
$applyAtKeyVaultLevel = $true
} elseif ($option -eq "2") {
$applyAtKeyVaultLevel = $false
} else {
Write-Host "Invalid option selected. Exiting script." -ForegroundColor Red
exit 1
}
# Function to apply Key Vault policy (access policies only)
function Set-KeyVaultPolicy {
param(
[string]$KeyVaultName,
[string]$Subscription,
[string]$AppId,
[bool]$DryRun
)
Write-Output "Processing Key Vault: $KeyVaultName in subscription: $Subscription" | Green
if ($DryRun) {
Write-Output "DRY RUN: Would apply access policies for App ID '$AppId' to Key Vault: $KeyVaultName." | Green
} else {
Write-Output "Applying access policies for App ID '$AppId' to Key Vault: $KeyVaultName." | Green
az keyvault set-policy --subscription $Subscription --name $KeyVaultName --spn $AppId --key-permissions get wrapKey unwrapKey
}
}
function Green { process { Write-Host $_ -ForegroundColor Green } }
function Red { process { Write-Host $_ -ForegroundColor Red } }
# Check if the user is logged in to Azure
$loggedIn = az account show --output none 2>&1
if ($LASTEXITCODE -ne 0) {
Write-Host "You are not logged in to Azure. Please run 'az login' to log in."
Exit 1
}
# Microsoft Defender for Cloud Servers Scanner Resource Provider
$appId = '0c7668b5-3260-4ad0-9f53-34ed54fa19b2'
# Iterate over each subscription
foreach ($subscription in $Subscriptions) {
Write-Output "Processing subscription $subscription" | Green
# Get Disk Encryption Sets
$desIds = az disk list --subscription $subscription --query "[?encryption.diskEncryptionSetId != null].encryption.diskEncryptionSetId" --output json | ConvertFrom-Json | Sort-Object -Unique
if ($desIds.count -eq 0) {
Write-Output "No disk encryption sets found in subscription $subscription" | Green
continue
}
# Get Key Vaults associated with DES
$keyVaultIds = az disk-encryption-set show --ids @desIds --query "[].activeKey.sourceVault.id" --output json | ConvertFrom-Json | Sort-Object -Unique
if ($applyAtKeyVaultLevel) {
$response = Read-Host "Do you want to apply permissions for all Key Vaults or one-by-one?
(A)ll - Apply permissions to all Key Vaults
(O)ne-by-one - Ask for approval for each Key Vault"
foreach ($keyVaultId in $keyVaultIds) {
$keyVaultName = ($keyVaultId -split '/')[-1]
$keyVaultSubscription = ($keyVaultId -split '/')[2]
Write-Output "Processing Key Vault: $keyVaultName in subscription: $keyVaultSubscription" | Green
if ($response -eq "O" -or $response -eq "o") {
$confirm = Read-Host "Apply permissions to $keyVaultName? (Y/N)"
if ($confirm -ne "Y" -and $confirm -ne "y") {
Write-Output "Skipping Key Vault: $keyVaultName" | Green
continue
}
}
q
$response = Read-Host "Apply permissions to $keyVaultName? (Y/N)"
if ($response -ne "Y" -and $response -ne "y") {
Write-Output "Skipping Key Vault: $keyVaultName" | Green
continue
}
# Check if the Key Vault is RBAC or Access Policy-based
$keyVaultProperties = az keyvault show --subscription $subscription --name $keyVaultName --query "properties" --output json | ConvertFrom-Json
$keyVaultRbacEnabled = $keyVaultProperties.enableRbacAuthorization -eq $true
Write-Output "Key Vault: $keyVaultName, RBAC Enabled: $keyVaultRbacEnabled" | Green
# Apply permissions at the Key Vault level
if ($keyVaultRbacEnabled) {
if ($DryRun) {
Write-Output "DRY RUN: Would apply RBAC permissions for App ID '$appId' to Key Vault: $keyVaultName." | Green
} else {
Write-Output "Applying RBAC permissions for App ID '$appId' to Key Vault: $keyVaultName." | Green
az role assignment create --assignee $appId --role "Key Vault Crypto Service Encryption User" --scope $keyVaultId
}
} else {
Set-KeyVaultPolicy -KeyVaultName $keyVaultName -Subscription $subscription -AppId $appId -DryRun $DryRun
}
}
} else {
# Apply RBAC permissions at the subscription level (default)
Write-Output "Applying RBAC permissions at the subscription level for App ID '$appId' in subscription $subscription." | Green
if ($DryRun) {
Write-Output "DryRun mode enabled. No changes will be made for subscription: $subscription." | Green
} else {
Write-Output "Applying RBAC permissions for App ID '$appId' at subscription scope." | Green
az role assignment create --assignee $appId --role "Key Vault Crypto Service Encryption User" --scope "/subscriptions/$subscription"
}
$accessPolicyKVs = @()
foreach ($keyVaultId in $keyVaultIds) {
$keyVaultName = ($keyVaultId -split '/')[-1]
$keyVaultSubscription = ($keyVaultId -split '/')[2]
# Check if RBAC is enabled on the Key Vault
$keyVaultProperties = az keyvault show --subscription $keyVaultSubscription --name $keyVaultName --query "properties.enableRbacAuthorization" --output json | ConvertFrom-Json
$keyVaultRbacEnabled = $keyVaultProperties -eq $true
if (-not $keyVaultRbacEnabled) {
$accessPolicyKVs += $keyVaultId
}
}
if ($accessPolicyKVs.Count -gt 0) {
Write-Output "Found $( $accessPolicyKVs.Count ) Key Vault(s) using Access Policies. They need separate permission setup." | Red
$response = Read-Host "Do you want to apply Key Vault permissions for access policy Key Vaults?
(A)ll - Apply permissions to all access policy Key Vaults
(O)ne-by-one - Ask for approval for each Key Vault
(N)o - Skip access policy Key Vaults"
if ($response -eq "N" -or $response -eq "n") {
Write-Output "Skipping all access policy Key Vaults." | Green
continue
}
foreach ($kvId in $accessPolicyKVs) {
$kvName = ($kvId -split '/')[-1]
Write-Output "Processing Key Vault: $kvName" | Green
if ($response -eq "O" -or $response -eq "o") {
$confirm = Read-Host "Apply permissions to $kvName? (Y/N)"
if ($confirm -ne "Y" -and $confirm -ne "y") {
Write-Output "Skipping Key Vault: $kvName" | Green
continue
}
}
if ($DryRun) {
Write-Output "DryRun mode enabled. No changes will be made for Key Vault: $kvName." | Green
} else {
Set-KeyVaultPolicy -KeyVaultName $kvName -Subscription $subscription -AppId $appId -DryRun $DryRun
}
}
}
}
}
Write-Output "Script execution complete." | Green